package com.story.rpc.transmission.socket.server;

import com.story.rpc.config.RpcServiceConfig;
import com.story.rpc.dto.RpcReq;
import com.story.rpc.dto.RpcResp;
import com.story.rpc.handler.RpcReqHandler;
import com.story.rpc.provider.ServiceProvider;
import com.story.rpc.provider.impl.SimpleServiceProvider;
import com.story.rpc.transmission.RpcServer;
import com.story.rpc.util.ThreadPoolUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;

@Slf4j
public class SocketRpcServer implements RpcServer {
    private final int port;
    private final RpcReqHandler rpcReqHandler;
    private final ServiceProvider serviceProvider;
    private final ExecutorService executorService;
    private final String poolName = "socket-rpc-server-";
    public SocketRpcServer(int port) {
        this(port, new SimpleServiceProvider());
    }

    public SocketRpcServer(int port, ServiceProvider serviceProvider) {
        this.port = port;
        this.serviceProvider = serviceProvider;
        this.rpcReqHandler = new RpcReqHandler(serviceProvider);
        this.executorService = ThreadPoolUtils.createIoIntensiveThreadPool(poolName);
    }
    @Override
    public void start() {
        try(ServerSocket serverSocket = new ServerSocket(port)){
            log.info("SocketRpcServer start, port: {}", port);
            Socket socket;
            while((socket = serverSocket.accept())!=null){
                executorService.submit(new SocketReqHandler(socket,rpcReqHandler));
            }
        }catch(Exception e){
            log.error("服务端异常",e);
        }
    }

    @Override
    public void pulishService(RpcServiceConfig config) {
        serviceProvider.publicService(config);
    }

    @SneakyThrows
    private Object invoke(RpcReq req){
        String rpcServiceName = req.rpcServiceName();
        Object service = serviceProvider.getService(rpcServiceName);
        log.debug("获取到对应服务 :{} ",service.getClass().getCanonicalName());
        Method method = service.getClass().getMethod(req.getMethodName(), req.getParamTypes());
        Object result = method.invoke(service, req.getParams());
        return result;
    }
}
